11장 Next.js 13과 리액트 18
1. app 디렉터리의 등장
12 버전 까지 페이지 공통 레이아웃을 유지하기 위한 작업은 _app에서 밖에 할 수 없었다. 그로 인해 각 페이지 별로 다른 레이아웃을 적용할 수가 없었고, 제한적인 환경의 한계를 극복하기 위해 app 레이아웃을 개발했다.
1. 12 버전 까지의 기능
-
_document: 페이지에서 쓰이는
<html>
과<body>
태그를 수정하거나, 서버 사이드 렌더링 시 styled-components 같은 일부 CSS-in-JS를 지원하기 위한 코드를 삽입하는 제한적인 용도로 사용된다. 오직 서버에서만 작동하므로 onClick 같은 이벤트 핸들러를 붙이거나 클라이언트 로직을 붙이는 것을 금지하고 있다. -
_app: 페이지를 초기화하기 위한 용도로 사용되며, 다음과 같은 작업이 가능하다고 명시돼 있다.
- 페이지 변경 시에 유지하고 싶은 레이아웃
- 페이지 변경 시 상태 유지
- ComponentDidCatch를 활용한 에러 핸들링
- 페이지간 추가적인 데이터 삽입
- global CSS 주입
2. 라우팅
/pages
로 정의하던 라우팅 방식이 /app
디렉터리로 이동했다.
1. 라우팅을 정의하는 법
- Next.js 12 이하: /pages/a/b.tsx 또는 /pages/a/b/index.tsx는 모두 동일한 주소로 변환된다. 즉, 파일명이index라 면 이 내용은 무시된다.
- Next.js 13 app: /app/a/b는 /a/b로 변환되며, 파일명은 무시된다. 폴더명까지만 주소로 변환된다.
2. layout.js
페이지의 기본적인 레이아웃을 구성하는 요소다. 해당 폴더에 layout이 있다면 그 하위 폴더 및 주소에 모두 영향을 미친다.
// app/layout.tsx
import { ReactNode } from 'react'
export default function AppLayout({ children }: { children: ReactNode }) {
return (
<html lang="ko">
<head>
<title>안녕하세요!</title>
</head>
<body>
<h1>웹페이지에 오신 것을 환영합니다.</h1>
<main>{children}</main>
</body>
</html>
)
}
// app/blog/layout.tsx
import { ReactNode } from 'react'
export default function BlogLayout({ children }: { children: ReactNode }) {
return <section>{children}</section>
}
- 공통 UI를 포함할 수 있으며, 공통 코드는 자신과 자식 라우팅에만 미치게 된다. 하위 페이지에 추가된 레이아웃은 해당 주소 하위에만 적용된다.
주의할 점
-
layout은 app 디렉터리 내부에서는 예약어다. 무조건
layout.{js|jsx|ts|tsx}
로 사용해야 하며, 레이아웃 이외의 다른 목적으로는 사용할 수 없다. -
layout은 children을 props로 받아서 렌더링해야 한다. 레이아웃이므로 당연히 그려야 할 컴포넌트를 외부에서 주입받고 그려야 한다.
-
layout 내부에는 반드시 export default로 내보내는 컴포넌트가 있어야 한다.
-
layout 내부에서도 API 요청과 같은 비동기 작업을 수행할 수 있다.